<template>
  <div class="upload-container">
    <h1 class="title">图片处理工具</h1>

    <div class="upload-box">
      <label class="file-input-label">
        <input type="file" @change="onFileChange" class="file-input" accept="image/*" />
        <span class="file-input-button">选择图片</span>
        <span v-if="file" class="file-name">{{ file.name }}</span>
      </label>

      <button
          @click="uploadImage"
          class="upload-button"
          :disabled="!file || isUploading"
      >
        <span v-if="!isUploading">上传处理</span>
        <span v-else class="loading">
          <span class="loading-dot">.</span>
          <span class="loading-dot">.</span>
          <span class="loading-dot">.</span>
        </span>
      </button>
    </div>

    <!-- 图片展示区域 -->
    <div class="image-preview-container">
      <!-- 原始图片 -->
      <div class="image-preview" v-if="originalImageUrl">
        <h3 class="preview-title">原始图片</h3>
        <div class="image-wrapper">
          <img :src="originalImageUrl" alt="Original Image" class="preview-image" />
        </div>
      </div>

      <!-- 处理后的图片 -->
      <div class="image-preview" v-if="newImageUrl">
        <h3 class="preview-title">处理后的图片</h3>
        <div class="image-wrapper">
          <img :src="newImageUrl" alt="Processed Image" class="preview-image" />
          <a :href="newImageUrl" download="processed-image.jpg" class="download-button">下载图片</a>
        </div>
      </div>
    </div>

    <!-- 错误提示卡片 -->
    <transition name="fade">
      <div v-if="showErrorCard" class="error-card-overlay" @click.self="closeErrorCard">
        <div class="error-card">
          <div class="error-card-header">
            <svg class="error-icon" viewBox="0 0 24 24">
              <path fill="currentColor" d="M11,15H13V17H11V15M11,7H13V13H11V7M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20Z" />
            </svg>
            <h3>上传出错</h3>
          </div>
          <div class="error-card-body">
            <p>{{ errorMessage }}</p>
          </div>
          <div class="error-card-footer">
            <button @click="closeErrorCard" class="error-card-button">我知道了</button>
            <button
                v-if="isRetryable"
                @click="retryUpload"
                class="error-card-button retry-button"
            >
              重试上传
            </button>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      file: null,
      originalImageUrl: '',
      newImageUrl: '',
      isUploading: false,
      maxFileSize: 10 * 1024 * 1024, // 5MB限制
      allowedTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
      showErrorCard: false,
      errorMessage: '',
      isRetryable: false,
      lastFormData: null
    };
  },
  methods: {
    onFileChange(event) {
      const file = event.target.files[0];
      if (!file) return;

      // 检查文件类型
      if (!this.allowedTypes.includes(file.type)) {
        this.showError('仅支持JPEG、PNG、GIF或WebP格式的图片', false);
        this.resetFileInput(event.target);
        return;
      }

      // 检查文件大小
      if (file.size > this.maxFileSize) {
        this.showError(`图片大小不能超过${this.formatFileSize(this.maxFileSize)}`, false);
        this.resetFileInput(event.target);
        return;
      }

      this.file = file;
      this.originalImageUrl = URL.createObjectURL(this.file);
      this.newImageUrl = '';
    },

    async uploadImage() {
      if (!this.file) {
        this.showError('请先选择有效的图片文件', false);
        return;
      }

      this.isUploading = true;
      this.isRetryable = false;

      const formData = new FormData();
      formData.append('file', this.file);
      this.lastFormData = formData; // 保存用于重试

      try {
        const response = await axios.post('http://localhost:8887/image/upload', formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
          timeout: 30000 // 30秒超时
        });

        if (response.data.code === 200) {
          this.newImageUrl = `http://localhost:8886/static/${response.data.data.newurl}`;
          this.showSuccess('图片处理成功！');
        } else {
          this.showError(response.data.message || '图片处理失败', false);
        }
      } catch (error) {
        this.handleUploadError(error);
      } finally {
        this.isUploading = false;
      }
    },

    handleUploadError(error) {
      let message = '上传失败';
      let retryable = false;

      if (error.response) {
        // 处理HTTP错误响应
        switch (error.response.status) {
          case 413:
            message = '文件太大，服务器拒绝处理 (最大限制5MB)';
            break;
          case 415:
            message = '不支持的图片格式';
            break;
          case 500:
            message = '服务器处理图片时出错';
            retryable = true;
            break;
          default:
            message = `上传失败: ${error.response.data?.message || '服务器错误'}`;
            retryable = true;
        }
      } else if (error.request) {
        // 请求已发出但没有响应
        message = '文件太大，服务器拒绝处理，文件最大不超过10MB';
        retryable = true;
      } else {
        // 其他错误
        message = '上传失败: ' + (error.message || '未知错误');
      }

      this.showError(message, retryable);
    },

    resetFileInput(input) {
      input.value = '';
      this.file = null;
      this.originalImageUrl = '';
    },

    formatFileSize(bytes) {
      if (bytes === 0) return '0 Bytes';
      const k = 1024;
      const sizes = ['Bytes', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    },

    showError(message, retryable) {
      this.errorMessage = message;
      this.isRetryable = retryable;
      this.showErrorCard = true;
    },

    showSuccess(message) {
      // 这里可以添加成功提示，如果需要
      console.log('Success:', message);
    },

    closeErrorCard() {
      this.showErrorCard = false;
      this.errorMessage = '';
      this.isRetryable = false;
    },

    retryUpload() {
      this.closeErrorCard();
      if (this.lastFormData) {
        this.uploadImage();
      }
    }
  }
};
</script>

<style scoped>
/* 基础样式 */
:root {
  --primary-color: #4361ee;
  --secondary-color: #3f37c9;
  --accent-color: #4895ef;
  --light-color: #f8f9fa;
  --dark-color: #212529;
  --success-color: #4cc9f0;
  --error-color: #f72585;
  --card-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  line-height: 1.6;
  color: var(--dark-color);
  background-color: #f5f7fa;
}

.upload-container {
  max-width: 1000px;
  margin: 2rem auto;
  padding: 2rem;
  background: white;
  border-radius: 15px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
  position: relative;
}

.title {
  text-align: center;
  margin-bottom: 2rem;
  color: var(--primary-color);
  font-weight: 600;
  font-size: 2rem;
}

/* 上传区域样式 */
.upload-box {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: center;
  align-items: center;
  margin-bottom: 2rem;
  padding: 1.5rem;
  background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%);
  border-radius: 12px;
  border: 2px dashed #cbd5e0;
  transition: all 0.3s ease;
}

.upload-box:hover {
  border-color: var(--accent-color);
  background: linear-gradient(135deg, #f0f4f8 0%, #dfe6ee 100%);
}

.file-input-label {
  display: flex;
  align-items: center;
  gap: 1rem;
  cursor: pointer;
}

.file-input {
  display: none;
}

.file-input-button {
  padding: 0.75rem 1.5rem;
  background: var(--primary-color);
  color: white;
  border-radius: 8px;
  font-weight: 500;
  transition: all 0.3s ease;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.file-input-button:hover {
  background: var(--secondary-color);
  transform: translateY(-2px);
  box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
}

.file-name {
  font-size: 0.9rem;
  color: #4a5568;
  max-width: 200px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.upload-button {
  padding: 0.75rem 1.5rem;
  background: linear-gradient(to right, var(--primary-color), var(--accent-color));
  color: white;
  border: none;
  border-radius: 8px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.upload-button:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
  opacity: 0.9;
}

.upload-button:disabled {
  background: #cbd5e0;
  cursor: not-allowed;
  opacity: 0.7;
}

/* 加载动画 */
.loading {
  display: inline-block;
}

.loading-dot {
  animation: bounce 1.4s infinite ease-in-out;
  opacity: 0.6;
}

.loading-dot:nth-child(2) {
  animation-delay: 0.2s;
}

.loading-dot:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes bounce {
  0%, 80%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-6px);
  }
}

/* 图片预览区域 */
.image-preview-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  gap: 2rem;
  margin-top: 2rem;
}

.image-preview {
  background: white;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
  transition: transform 0.3s ease;
}

.image-preview:hover {
  transform: translateY(-5px);
}

.preview-title {
  padding: 1rem;
  background: linear-gradient(to right, var(--primary-color), var(--accent-color));
  color: white;
  text-align: center;
  font-size: 1.2rem;
}

.image-wrapper {
  padding: 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.preview-image {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
  margin-bottom: 1rem;
  transition: transform 0.3s ease;
}

.preview-image:hover {
  transform: scale(1.02);
}

.download-button {
  display: inline-block;
  padding: 0.5rem 1rem;
  background: var(--success-color);
  color: white;
  border-radius: 6px;
  text-decoration: none;
  font-weight: 500;
  transition: all 0.3s ease;
}

.download-button:hover {
  background: #3aa8d8;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* 错误提示卡片样式 */
.error-card-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.error-card {
  background: white;
  border-radius: 12px;
  width: 90%;
  max-width: 400px;
  overflow: hidden;
  box-shadow: var(--card-shadow);
  animation: slide-up 0.3s ease;
}

.error-card-header {
  padding: 1.5rem;
  background: #fff6f6;
  display: flex;
  align-items: center;
  gap: 1rem;
  border-bottom: 1px solid #ffe0e0;
}

.error-icon {
  width: 24px;
  height: 24px;
  color: var(--error-color);
}

.error-card-body {
  padding: 1.5rem;
  color: #555;
  line-height: 1.6;
}

.error-card-footer {
  padding: 1rem;
  display: flex;
  justify-content: flex-end;
  gap: 1rem;
  border-top: 1px solid #eee;
}

.error-card-button {
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 6px;
  background: #f0f0f0;
  color: #555;
  cursor: pointer;
  transition: all 0.2s ease;
}

.error-card-button:hover {
  background: #e0e0e0;
}

.retry-button {
  background: var(--primary-color);
  color: white;
}

.retry-button:hover {
  background: var(--secondary-color);
}

/* 动画效果 */
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}

@keyframes slide-up {
  from {
    transform: translateY(20px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

/* 响应式调整 */
@media (max-width: 768px) {
  .upload-container {
    padding: 1rem;
  }

  .image-preview-container {
    grid-template-columns: 1fr;
  }

  .upload-box {
    flex-direction: column;
  }

  .file-input-label {
    width: 100%;
    justify-content: center;
  }

  .error-card {
    width: 95%;
  }
}
</style>